'''
rgeViews - for the Random Game Generator project
By Doctus (kirikayuumura.noir@gmail.com)

Actions which occur in response to user commands.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
'''
import time, random, os, base64
import rgeMap, rgeTile, rgePog, rgeEditingTabs, rgeDialogs, rgeMenuBar, rgeSystem, rgeSession, rgeScene, rgeModule, rgeTileset, rgeMapeditor, rgeSave, rgeSprite, rgeActor
from rgeJson import jsondump, jsonload
from rgeMenuBar import ICON_SELECT, ICON_MOVE, ICON_DRAW, ICON_DELETE
from rgeEditingTabs import TILESET_TAB, LAYERS_ENABLED_TAB, MAP_EDITOR_TAB, SCENE_GENERAL_TAB, NOTHING_TAB, MODULE_GENERAL_TAB, SPRITE_SETTINGS_TAB, SPRITE_GENERAL_TAB, SPRITE_ANIMATION_TAB, ACTOR_SPRITES_TAB
from rgeSystem import *
from rgeDialogs import *
from rgeModule import *
from PyQt4 import QtCore, QtGui

# Button enum
BUTTON_LEFT = 0
BUTTON_MIDDLE = 1
BUTTON_RIGHT = 2
BUTTON_CONTROL = 3
BUTTON_SHIFT = 6

# editing mode enum
MODE_MODULE = 0
MODE_TILESET = 1
MODE_SCENE = 2
MODE_SPRITE = 3
MODE_ACTOR = 4

# windows enum
WINDOW_MAP = 0

class _state(object):
    """A state class build to avoid all these global statements."""

    session = rgeSession.Session()

    alert = True

    pogSelection = set()
    pogHover = None

    mouseButton = None
    mousePosition = (0, 0)

    pogPlacement = False
    pogPath = "path"

    fileFolder = ""

    editingMode = MODE_MODULE

    numberOfLayers = 20
    currentLayer = 0

    spriteAnimationNum = 0
    spriteAnimationFrameNum = 0

    pause = False



    @staticmethod
    def initialize(mainApp):
        _state.menu = rgeMenuBar.menuBar()

        _state.data = {}
        _state.data[MODE_MODULE] = None
        _state.data[MODE_TILESET] = None
        _state.data[MODE_SCENE] = None
        _state.data[MODE_SPRITE] = None
        _state.data[MODE_ACTOR] = None

        _state.sidebar = rgeEditingTabs.Sidebar(mainWindow)
        _state.windows = {}
        _state.spriteTiles = []
        setModuleMode()

        _state.App = mainApp

        try:
            mainWindow.readGeometry()
        except:
            pass

def drawPogCircles():
    clearSelectionCircles()
    for pog in _state.pogSelection:
        drawSelectionCircle(*pog.getSelectionCircleData())

def addPogSelection(pog):
    _state.pogSelection.add(pog)
    drawPogCircles()

def removePogSelection(pog):
    _state.pogSelection.remove(pog)
    drawPogCircles()

def setPogSelection(pog):
    _state.pogSelection = set()
    addPogSelection(pog)

def getSession():
    return _state.session

def getCurrentLayer():
    return _state.currentLayer

def newSomething():
    if _state.editingMode is MODE_MODULE:
        newModule()
    elif _state.editingMode is MODE_TILESET:
        newTileset()
    elif _state.editingMode is MODE_SCENE:
        newScene()
    elif _state.editingMode is MODE_SPRITE:
        newSprite()
    elif _state.editingMode is MODE_ACTOR:
        newActor()

def loadSomething():
    if _state.editingMode is MODE_MODULE:
        openModule()
    elif _state.editingMode is MODE_TILESET:
        openTileset()
    elif _state.editingMode is MODE_SCENE:
        openScene()
    elif _state.editingMode is MODE_SPRITE:
        openSprite()
    elif _state.editingMode is MODE_ACTOR:
        openActor()

def getGameFilepath():
    return _state.fileFolder


# all stuff

def setDataName(NewName, Type = _state.editingMode):
    _state.data[Type].setName(NewName)


def saveData(Type = _state.editingMode):
    _state.data[Type].saveData()

def saveDataDirect(Item):
    Item.saveData()

# module stuff

def saveCurrentMod():
    saveData(MODE_MODULE)

def saveModule(Mod):
    saveDataDirect(Mod)

def loadModule(Filename):
    ReturnValue = rgeModule.ModuleData()
    ReturnValue.loadFromFile(Filename)
    return ReturnValue

def newModule():
    ModuleDialog = newModuleDialog(mainWindow)

    if(ModuleDialog.exec_()):
        closeOpenStuff()
        _state.data[MODE_MODULE] = rgeModule.ModuleData(ModuleDialog.Name)
        _state.fileFolder = os.path.abspath(MODULE_DIR + '/' + _state.data[MODE_MODULE].name ).replace('\\', '/') + '/'
        saveCurrentMod()
        setModuleMode()

def openModule():
    filename = promptLoadFile("Load Module", '*' + MODULE_EXTENSION,MODULE_DIR)
    if not filename:
        return
    closeOpenStuff()
    _state.data[MODE_MODULE] = loadModule(filename)
    setModuleMode()
    TempName = os.path.basename(filename)
    _state.fileFolder = filename[:-len(TempName)]

def setModuleName(NewName):
    setDataName(NewName, MODE_MODULE)


def modSetStartingScene(NewScene):
    _state.data[MODE_MODULE].setStartingScene(NewScene)

def modSetPythonScript(NewScript):
    NewLoc = rgeSave.MoveFile(NewScript, SCRIPT_DIR + '/', _state.fileFolder)
    if NewLoc:
        _state.data[MODE_MODULE].setPythonScript(NewLoc)
    return NewLoc


def choosePythonScript():
    newScript = promptLoadFile("Load Script", '*' + '.py',RAWDATA_DIR)
    if newScript:
        return newScript
    else:
        return None

#tileset stuff

def newTileset():
    TilesetDialog = newTilesetDialog(mainWindow, _state.fileFolder)

    if(TilesetDialog.exec_()):
        _state.data[MODE_TILESET] = rgeTileset.TilesetData(TilesetDialog.name)
        _state.data[MODE_TILESET].setCurrentFilepath(TilesetDialog.filename)
        saveCurrentTileset()
        setTilesetMode()

def openTileset():
    Dialog = chooseTileset()
    if Dialog != None:
        _state.data[MODE_TILESET] = loadTileset(Dialog.selectedFile)
        setTilesetMode()

def loadTileset(Filename):
    ReturnValue = rgeTileset.TilesetData()
    ReturnValue.loadFromFile(Filename)
    return ReturnValue

def chooseTileset():
    Dialog = rgeDialogs.loadDataDialog(mainWindow, _state.fileFolder + TILESET_DIR, '*' + TILESET_EXTENSION)
    if(Dialog.exec_()):
        return Dialog
    else:
        return None

def changeTilesetImage():
    newImageLoc = promptLoadFile("Load Image", '*' + IMAGE_EXTENSIONS,RAWDATA_DIR)
    if not newImageLoc:
        return
    _state.data[MODE_TILESET].setCurrentFilepath(newImageLoc)
    updateTilesetDisplay()

def setTilesetName(newName):
    setDataName(newName, MODE_TILESET)

def saveCurrentTileset():
    saveData(MODE_TILESET)

def tilesetTileSizeX():
    Dialog = setValueDialog(mainWindow, "Tile Size X", _state.data[MODE_TILESET].getWidth())
    if Dialog.exec_():
        _state.data[MODE_TILESET].setWidth(Dialog.returnedValue)
        tilesetSetupMap()

def tilesetTileSizeY(NewValue):
    Dialog = setValueDialog(mainWindow, "Tile Size Y", _state.data[MODE_TILESET].getHeight())
    if Dialog.exec_():
        _state.data[MODE_TILESET].setHeight(Dialog.returnedValue)
        tilesetSetupMap()


def tilesetTileNumberX(NewValue):
    Dialog = setValueDialog(mainWindow, "Tile Number X", _state.data[MODE_TILESET].tileNumberX)
    if Dialog.exec_():
        _state.data[MODE_TILESET].setTileNumberX(Dialog.returnedValue)
        tilesetSetupMap()

def tilesetTileNumberY(NewValue):
    Dialog = setValueDialog(mainWindow, "Tile Number Y", _state.data[MODE_TILESET].tileNumberY)
    if Dialog.exec_():
        _state.data[MODE_TILESET].setTileNumberY(Dialog.returnedValue)
        tilesetSetupMap()

def tilesetSetupMap():
    setupMap(_state.data[MODE_TILESET], -1, -1, -1)
    updateBoxValues()

def updateBoxValues():
    if TILESET_TAB in _state.sidebar.widgets:
        _state.sidebar.widgets[TILESET_TAB].updateBoxValues(_state.data[MODE_TILESET])
    if MAP_EDITOR_TAB in _state.sidebar.widgets:
        _state.sidebar.widgets[MAP_EDITOR_TAB].updateBoxValues(_state.data[MODE_SCENE], _state.currentLayer)

def updateTilesetDisplay():
    _closeAllMaps()
    if mainWindow.glwidget.checkImageValid(_state.data[MODE_TILESET].getCurrentFilepath()):
        map  = rgeMap.Map(_state.data[MODE_TILESET].getCurrentFilepath(),_state.currentLayer)
        map.setDrawOffset([1,1])
        internalAddMap(map)
        tilesetSetupMap()
    else:
        print "Image filepath invalid! Path: " + _state.data[MODE_TILESET].getCurrentFilepath()




# scene stuff

def newScene():
    Dialog = rgeDialogs.newSceneDialog(mainWindow, _state.fileFolder)
    if(Dialog.exec_()):
        _state.data[MODE_SCENE] = rgeScene.SceneData(Dialog.name)
        saveCurrentScene()
        setSceneMode()

def openScene():
    Scene = chooseScene()
    if Scene != None:
        #try:
            _state.data[MODE_SCENE] = loadScene(Scene.selectedFile)
            setSceneMode()
        #except Exception as e:
        #    showErrorMessage(translate('views', "Unable to read {0}.").format(Scene.selectedFile))
        #    print e

def saveCurrentScene():
    saveData(MODE_SCENE)

def saveScene(Scene):
    saveDataDirect(Scene)

def setSceneName(NewName):
    setDataName(NewName, MODE_SCENE)


def chooseScene():
    Dialog = rgeDialogs.loadDataDialog(mainWindow, _state.fileFolder + SCENE_DIR, '*' + SCENE_EXTENSION)
    if(Dialog.exec_()):
        return Dialog
    else:
        return None

def loadScene(Filename):
    ReturnValue = rgeScene.SceneData()
    ReturnValue.loadFromFile(Filename)
    return ReturnValue

def chooseTilemap():
    """tilmap chooser dialog show"""


    tilemapDialog = sceneLoadTilesetDialog(mainWindow, _state.fileFolder + TILESET_DIR, '*' + TILESET_EXTENSION)

    if(tilemapDialog.exec_()):
        Tilemap = tilemapDialog.tilemap
        sceneDisplayMap(Tilemap, tilemapDialog.x, tilemapDialog.y, _state.currentLayer)
        _state.data[MODE_SCENE].setLayer(Tilemap, _state.currentLayer)
        sceneSetX(tilemapDialog.x)
        sceneSetY(tilemapDialog.y)
        updateBoxValues()
        if rgeEditingTabs.MAP_EDITOR_TAB in _state.sidebar.widgets:
            _state.sidebar.widgets[MAP_EDITOR_TAB].setSize(Tilemap.getWidth(), Tilemap.getHeight())
        sceneSetMapEditorMap()

def sceneDisplayMap(Tilemap, xWidth, yHeight, Layer, Tiles = None):
    if not rgeSave.loadData(Tilemap.getCurrentFilepath()):
        return
    map = rgeMap.Map(Tilemap.getCurrentFilepath(),Layer)
    map.setDrawOffset([0,0])
    internalAddMap(map)
    setupMap(Tilemap, Tilemap.getDefaultTile(), xWidth, yHeight, Tiles, Layer)

def sceneSetXButton():
    Dialog = setValueDialog(mainWindow, "X Width", _state.data[MODE_SCENE].getWidth(_state.currentLayer))
    if Dialog.exec_():
        sceneSetX(Dialog.returnedValue)

def sceneSetYButton():
    Dialog = setValueDialog(mainWindow, "Y Height", _state.data[MODE_SCENE].getHeight(_state.currentLayer))
    if Dialog.exec_():
        sceneSetY(Dialog.returnedValue)

def sceneSetX(NewX):
    setTilemapX(NewX)
    _state.data[MODE_SCENE].setWidth(NewX,_state.currentLayer)
    sceneUpdateMapSize()

def sceneSetY(NewY):
    setTilemapY(NewY)
    _state.data[MODE_SCENE].setHeight(NewY,_state.currentLayer)
    sceneUpdateMapSize()

def sceneSetNumOfLayers(NewNum):
    OldLayerAmount = _state.data[MODE_SCENE].getNumOfLayers()
    _state.data[MODE_SCENE].setLayerNum(NewNum)
    setNumberOfLayers(NewNum)
    NewLayerAmount = _state.data[MODE_SCENE].getNumOfLayers()
    if OldLayerAmount > NewLayerAmount:
        for i in range(NewLayerAmount, OldLayerAmount):
            sceneCloseMap(i)

def sceneSetCurrentLayer(NewNum):
    setCurrentLayer(NewNum)
    if rgeEditingTabs.MAP_EDITOR_TAB in _state.sidebar.widgets:
        _state.sidebar.widgets[MAP_EDITOR_TAB].updateBoxValues(_state.data[MODE_SCENE],_state.currentLayer)
    sceneSetMapEditorMap()

def sceneSetMapEditorMap():
    if WINDOW_MAP in _state.windows:
        _state.windows[WINDOW_MAP].changeMap(currentMap())

def sceneUpdateMapSize():
    if rgeEditingTabs.MAP_EDITOR_TAB in _state.sidebar.widgets:
        _state.sidebar.widgets[MAP_EDITOR_TAB].updateSize()
        _state.sidebar.widgets[MAP_EDITOR_TAB].updateBoxValues(_state.data[MODE_SCENE],_state.currentLayer)

def sceneCloseMap(layerNum = False):
    if not layerNum:
        layerNum = _state.currentLayer
    print layerNum
    _state.data[MODE_SCENE].removeTileset(layerNum)
    closeMap(layerNum)

def displayAllSceneMaps():
    for i in xrange(_state.data[MODE_SCENE].getNumOfLayers()):
        if _state.data[MODE_SCENE].getLayer(i) != "":
            sceneDisplayMap(_state.data[MODE_SCENE].getTileset(i), _state.data[MODE_SCENE].getWidth(i), _state.data[MODE_SCENE].getHeight(i), i, _state.data[MODE_SCENE].getTiles(i))

#sprite stuff

def newSprite():
    Dialog = rgeDialogs.newSpriteDialog(mainWindow, _state.fileFolder)
    if(Dialog.exec_()):
        _state.data[MODE_SPRITE] = rgeSprite.SpriteData(Dialog.name)
        saveCurrentSprite()
        setSpriteMode()

def openSprite():
    Sprite = chooseSprite()
    if Sprite != None:
        #try:
            _state.data[MODE_SPRITE] = loadSprite(Sprite.selectedFile)
            setSpriteMode()
        #except Exception as e:
        #    showErrorMessage(translate('views', "Unable to read {0}.").format(Sprite.selectedFile))
        #    print e


def loadSprite(Filename):
    ReturnValue = rgeSprite.SpriteData()
    ReturnValue.loadFromFile(Filename)
    return ReturnValue


def saveCurrentSprite():
    saveSprite(_state.data[MODE_SPRITE])

def saveSprite(Sprite):
    saveDataDirect(Sprite)


def chooseSprite():
    Dialog = rgeDialogs.loadDataDialog(mainWindow, _state.fileFolder + SPRITE_DIR, '*' + SPRITE_EXTENSION)
    if(Dialog.exec_()):
        return Dialog
    else:
        return None

def setSpriteName(NewName):
    setDataName(NewName, MODE_SPRITE)

def spriteNewTexture():
    Dialog = newTextureDialog(mainWindow, _state.fileFolder)
    if(Dialog.exec_()):
        _state.data[MODE_SPRITE].addTexture(Dialog.filename, Dialog.name)
        _state.currentLayer = _state.data[MODE_SPRITE].getTextureLength() - 1
        spriteUpdateTextureMenu()
        spriteTexturePreviewSetup()

def spriteRemoveTexture():
    if _state.currentLayer > 0:
        _state.data[MODE_SPRITE].removeTexture(_state.currentLayer)
        if _state.currentLayer >= _state.data[MODE_SPRITE].getTextureLength():
            _state.currentLayer = _state.data[MODE_SPRITE].getTextureLength() - 1
        spriteUpdateTextureMenu()
        spriteTexturePreviewSetup()
        spriteUpdateAnimationTab()

def spriteChangeTexture(NewValue):
    _state.currentLayer = NewValue
    spriteUpdateTextureMenu()
    spriteUpdateSplitsWindow()
    spriteTexturePreviewSetup()

def spriteUpdateTextureMenu():
    if SPRITE_SETTINGS_TAB in _state.sidebar.widgets:
        _state.sidebar.widgets[SPRITE_SETTINGS_TAB].updateTextures(_state.data[MODE_SPRITE], _state.currentLayer)
    spriteUpdateAnimationTab()

def spriteSetXSplit(NewValue):
    _state.data[MODE_SPRITE].setXSplit(NewValue, _state.currentLayer)
    spriteUpdateSplitsWindow()
    spriteTexturePreviewSetup()

def spriteSetYSplit(NewValue):
    _state.data[MODE_SPRITE].setYSplit(NewValue, _state.currentLayer)
    spriteUpdateSplitsWindow()
    spriteTexturePreviewSetup()


def spriteUpdateSplitsWindow():
    if SPRITE_SETTINGS_TAB in _state.sidebar.widgets:
        _state.sidebar.widgets[SPRITE_SETTINGS_TAB].updateSplits(_state.data[MODE_SPRITE], _state.currentLayer)

def spriteSplitTextureX():
    Dialog = setValueDialog(mainWindow, "Number of frames (x)", _state.data[MODE_SPRITE].getTextureSplit(_state.currentLayer)[0])
    if Dialog.exec_():
        spriteSetXSplit(Dialog.returnedValue)

def spriteSplitTextureY():
    Dialog = setValueDialog(mainWindow, "Number of frames (y)", _state.data[MODE_SPRITE].getTextureSplit(_state.currentLayer)[1])
    if Dialog.exec_():
        spriteSetYSplit(Dialog.returnedValue)

def setSpriteTextureName(NewName):
    _state.data[MODE_SPRITE].setTextureName(NewName, _state.currentLayer)
    spriteUpdateTextureMenu()

def spriteTexturePreviewSetup():
    _closeAllMaps()
    TexPath = _state.data[MODE_SPRITE].getTexturePath(_state.currentLayer)
    if not rgeSave.loadData(TexPath):
        TexPath = getGameFilepath() + TexPath
    if _state.data[MODE_SPRITE].getTextureLength() > _state.currentLayer and _state.currentLayer >= 0 and rgeSave.loadData(TexPath) is not None:
        map  = rgeMap.Map(TexPath,0)
        map.setDrawOffset([1,1])
        internalAddMap(map)
        Split = _state.data[MODE_SPRITE].getTextureSplit(_state.currentLayer)
        xWidth = Split[0]
        yHeight = Split[1]
        ImageSize = mainWindow.glwidget.getImageSize(TexPath)
        TileWidth = ImageSize.width() / xWidth
        TileHeight = ImageSize.height() / yHeight
        _state.session.maps[0].setMapProperties([xWidth,yHeight],[TileWidth, TileHeight], yHeight, xWidth)
        for x in xrange(0, xWidth):
            for y in xrange(0, yHeight):
                _state.session.maps[0].setTile([x,y], x + xWidth * y)
        _state.session.maps[0]._createTiles()

def spriteUpdateAnimationTab():
    if SPRITE_ANIMATION_TAB in _state.sidebar.widgets:
        _state.sidebar.widgets[SPRITE_ANIMATION_TAB].setupBoxes(_state.data[MODE_SPRITE], _state.spriteAnimationFrameNum, _state.spriteAnimationNum)


def spriteAnimationNameChanged(NewName):
    _state.data[MODE_SPRITE].changeAniName(NewName, _state.spriteAnimationNum)
    spriteUpdateAnimationTab()

def spriteAnimationChanged(NewValue):
    _state.spriteAnimationNum = NewValue
    _state.spriteAnimationFrameNum = 0
    spriteUpdateAnimationTab()
    spriteUpdateSprite()

def pauseSpriteAnimation():
    _state.pause = True

def advanceSpriteAnimation():
    if _state.pause: return
    try:
        _state.spriteAnimationFrameNum += 1
        spriteUpdateAnimationTab()
        spriteUpdateSprite()
    except IndexError:
        _state.spriteAnimationFrameNum = 0
        spriteUpdateAnimationTab()
        spriteUpdateSprite()
    QtCore.QTimer.singleShot(1000*_state.data[MODE_SPRITE].getTime(_state.spriteAnimationNum,_state.spriteAnimationFrameNum), advanceSpriteAnimation)

def playSpriteAnimation():
    _state.pause = False
    advanceSpriteAnimation()

def spriteAnimationFrameChanged(NewValue):
    _state.spriteAnimationFrameNum = NewValue
    spriteUpdateAnimationTab()
    spriteUpdateSprite()

def spriteCheckAniNum():
    if _state.spriteAnimationNum >= _state.data[MODE_SPRITE].getAnimationNum():
        _state.spriteAnimationNum = _state.data[MODE_SPRITE].getAnimationNum() - 1
        spriteCheckFrameNum()
        return True
    return False

def spriteCheckFrameNum():
    if _state.spriteAnimationFrameNum >= _state.data[MODE_SPRITE].getFrameNum(_state.spriteAnimationNum):
        _state.spriteAnimationFrameNum = _state.data[MODE_SPRITE].getFrameNum(_state.spriteAnimationNum) - 1
        return True
    return False

def spriteAniNumChanged():
    Dialog = setValueDialog(mainWindow, "Number of animations", _state.data[MODE_SPRITE].getAnimationNum(), 1, 10000)
    if Dialog.exec_():
        _state.data[MODE_SPRITE].changeAniNum(Dialog.returnedValue)
        if spriteCheckAniNum():
            spriteUpdateSprite()
        spriteUpdateAnimationTab()

def spriteNumFrameChanged():
    Dialog = setValueDialog(mainWindow, "Number of frames", _state.data[MODE_SPRITE].getFrameNum(_state.spriteAnimationNum), 1, 10000)
    if Dialog.exec_():
        _state.data[MODE_SPRITE].changeAniFrames(Dialog.returnedValue, _state.spriteAnimationNum)
        if spriteCheckFrameNum():
            spriteUpdateSprite()
        spriteUpdateAnimationTab()

def spriteFrameXChanged(NewValue):
    _state.data[MODE_SPRITE].changeAniValueX(NewValue, _state.spriteAnimationNum, _state.spriteAnimationFrameNum)
    spriteUpdateSprite()

def spriteFrameYChanged(NewValue):
    _state.data[MODE_SPRITE].changeAniValueY(NewValue, _state.spriteAnimationNum, _state.spriteAnimationFrameNum)
    spriteUpdateSprite()

def spriteOffsetXChanged(NewValue):
    _state.data[MODE_SPRITE].changeOffsetValueX(NewValue, _state.spriteAnimationNum, _state.spriteAnimationFrameNum)
    spriteUpdateSprite()

def spriteOffsetYChanged(NewValue):
    _state.data[MODE_SPRITE].changeOffsetValueY(NewValue, _state.spriteAnimationNum, _state.spriteAnimationFrameNum)
    spriteUpdateSprite()

def spriteOffsetBothChanged(NewX, NewY):
    _state.data[MODE_SPRITE].changeOffsetValueX(NewX, _state.spriteAnimationNum, _state.spriteAnimationFrameNum)
    _state.data[MODE_SPRITE].changeOffsetValueY(NewY, _state.spriteAnimationNum, _state.spriteAnimationFrameNum)
    spriteUpdateSprite()
    spriteUpdateAnimationTab()

def spriteAnimationTextureChanged(NewValue):
    _state.data[MODE_SPRITE].changeAniTexture(NewValue, _state.spriteAnimationNum, _state.spriteAnimationFrameNum)
    spriteUpdateAnimationTab()
    spriteUpdateSprite()

def spriteFlipXChanged(NewValue):
    _state.data[MODE_SPRITE].setXFlip(NewValue, _state.spriteAnimationNum, _state.spriteAnimationFrameNum)
    spriteUpdateSprite()

def spriteFlipYChanged(NewValue):
    _state.data[MODE_SPRITE].setYFlip(NewValue, _state.spriteAnimationNum, _state.spriteAnimationFrameNum)
    spriteUpdateSprite()

def spriteSizeXChanged(NewValue):
    _state.data[MODE_SPRITE].setXSize(NewValue, _state.spriteAnimationNum, _state.spriteAnimationFrameNum)
    spriteUpdateSprite()

def spriteSizeYChanged(NewValue):
    _state.data[MODE_SPRITE].setYSize(NewValue, _state.spriteAnimationNum, _state.spriteAnimationFrameNum)
    spriteUpdateSprite()


def spriteCenterChanged(NewValue):
    _state.data[MODE_SPRITE].setCenter(NewValue, _state.spriteAnimationNum, _state.spriteAnimationFrameNum)
    spriteUpdateSprite()


def spriteTimeChanged(NewValue):
    _state.data[MODE_SPRITE].setTime(NewValue, _state.spriteAnimationNum, _state.spriteAnimationFrameNum)


def spriteAnimationCopyFrame():
    _state.data[MODE_SPRITE].copyFrame(_state.spriteAnimationNum, _state.spriteAnimationFrameNum)
    spriteUpdateAnimationTab()


def spriteAnimationCopyAnimation():
    _state.data[MODE_SPRITE].setCopyNum(_state.spriteAnimationNum)
    spriteUpdateAnimationTab()


def spriteAnimationPasteAnimation():
    _state.data[MODE_SPRITE].copyAnimation(_state.spriteAnimationNum)
    spriteUpdateAnimationTab()
    spriteUpdateSprite()


def spriteMakeSprite():
    spriteClearSprites()
    _state.spriteTiles.append(rgePog.SpriteTile(_state.data[MODE_SPRITE], _state.spriteAnimationNum, _state.spriteAnimationFrameNum))


def spriteUpdateSprite():
    if len(_state.spriteTiles) > 0:
        _state.spriteTiles[0].update(_state.data[MODE_SPRITE], _state.spriteAnimationNum, _state.spriteAnimationFrameNum)

def spriteClearSprites():
    for x in _state.spriteTiles:
        x.deleteTile()
    _state.spriteTiles = []


# actors


def newActor():
    Dialog = rgeDialogs.newActorDialog(mainWindow, _state.fileFolder)
    if(Dialog.exec_()):
        _state.data[MODE_ACTOR] = rgeActor.ActorData(Dialog.name)
        saveCurrentActor()
        setActorMode()


def openActor():
    Actor = chooseActor()
    if Actor != None:
        #try:
            _state.data[MODE_ACTOR] = loadActor(Actor.selectedFile)
            setActorMode()
        #except Exception as e:
        #    showErrorMessage(translate('views', "Unable to read {0}.").format(Sprite.selectedFile))
        #    print e


def loadActor(Filename):
    ReturnValue = rgeActor.ActorData()
    ReturnValue.loadFromFile(Filename)
    return ReturnValue

def chooseActor():
    Dialog = rgeDialogs.loadDataDialog(mainWindow, _state.fileFolder + ACTOR_DIR, '*' + ACTOR_EXTENSION)
    if(Dialog.exec_()):
        return Dialog
    else:
        return None


def saveCurrentActor():
    saveActor(_state.data[MODE_ACTOR])

def saveActor(Actor):
    saveDataDirect(Actor)

def setActorName(NewName):
    setDataName(NewName, MODE_ACTOR)


def actorAddSprite():
    Sprite = chooseSprite()
    if Sprite:
        spritePath = SPRITE_DIR + '/' + os.path.basename(str(Sprite.selectedFile))
        spriteName = rgeSave.getName(Sprite.selectedFile)
        _state.data[MODE_ACTOR].addSprite(spritePath, spriteName)
        actorUpdateSpriteMenu()

def actorRemoveSprite():
    _state.data[MODE_ACTOR].removeSprite(_state.currentLayer)
    actorUpdateSpriteMenu()

def actorSpriteIndexChanged(NewIndex):
    _state.currentLayer = NewIndex
    actorUpdateSpriteMenu()

def actorHideChanged(Value):
    _state.data[MODE_ACTOR].flipHideSprite(_state.currentLayer, Value)

def actorSizeXChanged(Value):
    _state.data[MODE_ACTOR].setSizeX(Value)

def actorSizeYChanged(Value):
    _state.data[MODE_ACTOR].setSizeY(Value)

def actorUpdateSpriteMenu():
    if ACTOR_SPRITES_TAB in _state.sidebar.widgets:
        _state.currentLayer = _state.sidebar.widgets[ACTOR_SPRITES_TAB].updateMenu(_state.data[MODE_ACTOR])


#extras


def addExtraInt():
    Dialog = setExtraIntDialog(mainWindow, _state.data[_state.editingMode].data.data)
    if Dialog.exec_():
        _state.data[_state.editingMode].addExtra(Dialog.returnedExtra)



# modes
def setModuleMode():
    _state.editingMode = MODE_MODULE
    clearEverything()
    if setNothingTab("Module"):
        _state.sidebar.addTab(rgeEditingTabs.moduleGeneralSettingsPalette(mainWindow, _state.data[MODE_MODULE]))
        return

def setTilesetMode():
    if _state.data[MODE_MODULE] == None:
        showErrorMessage("No module currently loaded")
        return
    _state.editingMode = MODE_TILESET
    clearEverything()
    setCurrentLayer(0)
    if setNothingTab("Tileset"):
        updateTilesetDisplay()
        _state.sidebar.addTab(rgeEditingTabs.tilesetSettingsPalette(mainWindow, _state.data[MODE_TILESET]))


def setSceneMode():
    if _state.data[MODE_MODULE] == None:
        showErrorMessage("No module currently loaded")
        return
    _state.editingMode = MODE_SCENE
    clearEverything()
    if setNothingTab("Scene"):
        setCurrentLayer(0)
        displayAllSceneMaps()
        _state.sidebar.addTab(rgeEditingTabs.sceneGeneralSettingsTab(mainWindow, _state.data[MODE_SCENE]))
        _state.sidebar.addTab(rgeEditingTabs.layerSetValuesPalette(mainWindow, _state.data[MODE_SCENE], _state.currentLayer))
        _state.sidebar.addTab(rgeEditingTabs.layerEnabledPalette(mainWindow, _state.data[MODE_SCENE]))
        _state.windows[WINDOW_MAP] = rgeMapeditor.mapEditor(mainWindow)
        sceneSetMapEditorMap()

def setSpriteMode():
    if _state.data[MODE_MODULE] == None:
        showErrorMessage("No module currently loaded")
        return
    _state.editingMode = MODE_SPRITE
    clearEverything()
    if setNothingTab("Sprite"):
        setCurrentLayer(0)
        _state.sidebar.addTab(rgeEditingTabs.spriteGeneralSettingsTab(mainWindow, _state.data[MODE_SPRITE]))
        _state.sidebar.addTab(rgeEditingTabs.spriteSettingsPalette(mainWindow, _state.data[MODE_SPRITE], _state.currentLayer))
        _state.sidebar.addTab(rgeEditingTabs.spriteAnimationPalette(mainWindow, _state.data[MODE_SPRITE]))
        spriteTexturePreviewSetup()
        centerCamera()

def setActorMode():
    if _state.data[MODE_MODULE] == None:
        showErrorMessage("No module currently loaded")
        return
    _state.editingMode = MODE_ACTOR
    clearEverything()
    if setNothingTab("Actor"):
        setCurrentLayer(0)
        _state.sidebar.addTab(rgeEditingTabs.actorGeneralSettingsTab(mainWindow, _state.data[MODE_ACTOR]))
        _state.sidebar.addTab(rgeEditingTabs.actorSpritesTab(mainWindow, _state.data[MODE_ACTOR]))
        centerCamera()



def closeOpenStuff():
    clearEverything()
    _state.data[MODE_MODULE] = None
    _state.data[MODE_TILESET] = None
    _state.data[MODE_SCENE] = None
    _state.data[MODE_SPRITE] = None
    _state.data[MODE_ACTOR] = None


def clearEverything():
    resetSpriteAnimations()
    _state.sidebar.clearTabs()
    _closeAllMaps()
    closeWindows()
    clearLines()
    spriteClearSprites()


def setNothingTab(Name):
    if _state.data[_state.editingMode] is None:
        _state.sidebar.addTab(rgeEditingTabs.nothingLoadedPalette(mainWindow, Name))
        return False
    return True


def resetSpriteAnimations():
    _state.spriteAnimationNum = 0
    _state.spriteAnimationFrameNum = 0


def TabChanged(NewTabNum):
    if _state.editingMode == MODE_SPRITE:
        if _state.sidebar.widget.currentWidget() is not None:
            if _state.sidebar.widget.currentWidget().widgetName == SPRITE_ANIMATION_TAB:
                _closeAllMaps()
                drawCrosshair()
                spriteMakeSprite()
            elif _state.sidebar.widget.currentWidget().widgetName == SPRITE_SETTINGS_TAB:
                spriteTexturePreviewSetup()
                spriteClearSprites()

# MAPS
def topmap(mapPosition):
    return _state.session.findTopMap(mapPosition)

def currentMap():
    return _state.session.getMap(_state.currentLayer)

def getmap(mapID):
    return _state.session.getMap(mapID)

def allmaps():
    return _state.session.maps.items()

def getAllMaps():
    return _state.session.maps.values()

def chooseMap():
    say(translate('views', 'This function is deprecated. Use the view controller.'))
    return

def _closeAllMaps():
    clearPogSelection()
    clearLines()
    _state.session.closeAllMaps()

def closeAllMaps():
    _closeAllMaps()

def internalAddMap(map):
    _state.session.addMap(map)

def closeMap(mapNum):
    '''closes maps'''

    _state.session.closeMap(mapNum)

def closeWindows():
    for Window in _state.windows:
        _state.windows[Window].close()

def setTilemapX(NewValue):
    _state.session.maps[_state.currentLayer].setMapSizeX(NewValue)

def setTilemapY(NewValue):
    _state.session.maps[_state.currentLayer].setMapSizeY(NewValue)

def setTileSizeX(NewValue):
    _state.session.maps[_state.currentLayer].setTilesizeX(NewValue)

def setTileSizeY(NewValue):
    _state.session.maps[_state.currentLayer].setTilesizeY(NewValue)

def setMapProperties(mapsize, tilesize, yHeight, xWidth, Layer = _state.currentLayer):
    _state.session.maps[Layer].setMapProperties(mapsize, tilesize, yHeight, xWidth)

def setupMap(tileset, defaultTile, defaultWidth, defaultHeight, Tiles = None, Layer = _state.currentLayer):
    TempWidth = tileset.getTileNumX()
    TempHeight = tileset.getTileNumY()
    if(defaultWidth > 0):
        TempWidth = defaultWidth
    if defaultHeight > 0:
        TempHeight = defaultHeight
    setMapProperties([TempWidth, TempHeight], [tileset.getWidth(), tileset.getHeight()], tileset.getTileNumY(), tileset.getTileNumX(), Layer)
    for x in xrange(0, TempWidth):
        for y in xrange(0, TempHeight):
            if defaultTile < 0:
                _state.session.maps[Layer].setTile([x,y], x + TempWidth * y)
            else:
                if Tiles != None:
                    _state.session.maps[Layer].setTile([x,y], Tiles[x + TempWidth * y])
                else:
                    _state.session.maps[Layer].setTile([x,y], defaultTile)
    _state.session.maps[Layer]._createTiles()

def setTile(changingTile, newTile):
    _state.session.maps[_state.currentLayer].setTile(changingTile, newTile)
    if _state.editingMode == MODE_SCENE:
        _state.data[MODE_SCENE].setTile(newTile, changingTile[0] + (changingTile[1] * _state.data[MODE_SCENE].getWidth(_state.currentLayer)), _state.currentLayer)


def drawCrosshair():
    clearLines()
    mainWindow.glwidget.addLine(1,0,-25,0,25,1,1,1)
    mainWindow.glwidget.addLine(1,-25,0,25,0,1,1,1)


def clearLines():
    mainWindow.glwidget.clearLines()


def centerCamera():
    setCameraPosition([350,350])


def configureGfx():
    """Allows the user to the opengl settings."""
    dialog = gfxSettingsDialog()

    def accept():
        valid = dialog.is_valid()
        if not valid:
            showErrorMessage(dialog.error)
        return valid

    if dialog.exec_(mainWindow, accept):
        settings = dialog.save()
        jsondump(settings,  os.path.join(SAVE_DIR, "gfx_settings.rgs"))

def setLanguage(new):
    jsondump(dict(language=str(new.iconText())), os.path.join(SAVE_DIR, "lang_settings.rgs"))
    #This should ideally be translated into the newly selected language, but I have no idea how to accomplish that.
    info = QtGui.QMessageBox(QtGui.QMessageBox.Information, "Language Changed", "".join(('Your new language setting "', str(new.iconText()), '" will take effect the next time you start RGG.')), QtGui.QMessageBox.Ok)
    info.exec_()

def clearPogSelection():
    _state.pogSelection = set()
    if _state.pogHover != None:
        _state.pogHover.showTooltip = False
        _state.pogHover = None
    drawPogCircles()

def createPog(pog):
    """Creates a new pog."""
    pog.ID = _state.session._findUniquePogID(pog.src)
    _state.session.addPog(pog)

def placePog(pogpath):
    """Places a pog on the map."""
    _state.pogPlacement = True
    _state.pogPath = pogpath

def movePogs(displacement):
    """Moves pogs by a specified displacement."""
    selection = _state.pogSelection.copy()
    pogids = []
    poglocs = []
    for pog in selection:
        pog.displace(displacement)
    drawPogCircles()


def setNumberOfLayers(NewNumber):
    _state.numberOfLayers = NewNumber
    if rgeEditingTabs.MAP_EDITOR_TAB in _state.sidebar.widgets:
        _state.sidebar.widgets[MAP_EDITOR_TAB].setLayerAmount(NewNumber)
    if LAYERS_ENABLED_TAB in _state.sidebar.widgets:
        _state.sidebar.widgets[LAYERS_ENABLED_TAB].setLayers(NewNumber)

def setCurrentLayer(NewNumber):
    _state.currentLayer = NewNumber

def toggleLayerVisibility(layers):
    for layer in layers:
        m = None
        try:
            m = _state.session.maps[layer]
        except:
            continue

        m.hide(not m.hidden)

# MISC

def reportCamera():
    """Reports the current camera coordinates."""
    say(translate('views', 'x: {0}\ny: {1}', 'formats camera reporting.').format(*cameraPosition()))

def renamePog(pog, name):
    pog.name = name

def processPogRightclick(selection, pogs):
    #0 CENTER
    #1 SET NAME
    #2 [UNUSED]
    #3 SET LAYER
    #4 SET PROPERTY
    #5 RESIZE
    #6 HIDE
    #7 LOCK
    #8 DELETE
    mainpog = pogs[0]
    if selection == 0:
        camsiz = cameraSize()
        camzoom = getZoom()
        pospog = mainpog.position
        cammod = [(-camsiz[0]/2)+mainpog._tile.getW()/2, (-camsiz[1]/2)+mainpog._tile.getH()/2]
        newpos = (-(pospog[0]*camzoom + cammod[0]), -(pospog[1]*camzoom + cammod[1]))
        setCameraPosition(newpos)
    elif selection == 1:
        name = promptString(translate('views', "Enter a name for this pog."), inittext = mainpog.name)
        if name is None:
            return
        for pog in pogs:
            renamePog(pog, name)
    elif selection == 2:
        pass
    elif selection == 3:
        prompt = translate('views', "Enter a layer. Pogs on higher layers are displayed over those on lower layers. Should be a positive integer. Multi-pog compatible.")
        newlayer = promptInteger(prompt, min=-150, max=800, default=(mainpog.layer-200))
        if newlayer is None:
            return
        for pog in pogs:
            pog.layer = newlayer+200
    elif selection == 4:
        prompt = translate('views', 'Enter a name for the property (like "Level" or "HP").')
        key = promptString(prompt)
        prompt2 = translate('views', 'Enter a value for the property.')
        value = promptString(prompt2)
        if key is None or value is None:
            return
        for pog in pogs:
            pog.editProperty(key, value)
    elif selection == 5:
        d = rgeDialogs.resizeDialog(mainpog._tile.getW(), mainpog._tile.getH(), mainpog.size[0], mainpog.size[1])
        if d.exec_():
            for pog in pogs:
                pog.size = (d.wBox.value(), d.hBox.value())
                drawPogCircles()
    elif selection == 6:
        for pog in pogs:
            if pog.hidden:
                pog.show()
            else:
                pog.hide()
            clearPogSelection()
            drawPogCircles()
    elif selection == 7:
        for pog in pogs:
            pog._locked = not pog._locked
    elif selection == 8:
        for pog in pogs:
            deletePog(pog)

# MOUSE ACTIONS

def mouseDrag(screenPosition, mapPosition, displacement):
    if _state.pogSelection and _state.mouseButton == BUTTON_LEFT:
        movePogs(displacement)
        return
    elif _state.mouseButton == BUTTON_LEFT:
        setCameraPosition(map(lambda c, d,  z: c + d*z, cameraPosition(), displacement, (getZoom(), getZoom())))
        return
    if _state.mouseButton == BUTTON_RIGHT:
        setCameraPosition(map(lambda c, d,  z: c + d*z, cameraPosition(), displacement, (getZoom(), getZoom())))

def mouseMove(screenPosition, mapPosition, displacement):
    return
    #stuff below unused
    icon = _state.menu.selectedIcon
    if icon == ICON_MOVE: # moveIcon
        if _state.mouseButton == BUTTON_LEFT:
            setCameraPosition(map(lambda c, d,  z: c + d*z, cameraPosition(), displacement, (getZoom(), getZoom())))
        elif _state.mouseButton == BUTTON_RIGHT:
            if topmap(mapPosition) is None:
                return
            drawOffset = list(topmap(mapPosition).drawOffset)
            drawOffset[0] += displacement[0]*getZoom()
            drawOffset[1] += displacement[1]*getZoom()
            topmap(mapPosition).drawOffset = drawOffset
        return
    if icon == ICON_SELECT: #selectIcon
        if _state.mouseButton is None:
            tooltipPog = _state.session.findTopPog(mapPosition)
            if _state.pogHover == tooltipPog:
                return
            elif _state.pogHover != None:
                _state.pogHover.showTooltip = False
            _state.pogHover = tooltipPog
            if tooltipPog is None:
                return

            tooltipPog.showTooltip = True
        elif _state.mouseButton == BUTTON_LEFT:
            return mouseDrag(screenPosition, mapPosition, displacement)
        elif _state.mouseButton == BUTTON_RIGHT:
            return mouseDrag(screenPosition, mapPosition, displacement)
    elif icon == ICON_DRAW: #drawIcon
        if _state.mouseButton == BUTTON_LEFT:
            if _state.previousLinePlacement != None:
                drawLine(_state.previousLinePlacement[0], _state.previousLinePlacement[1], mapPosition[0], mapPosition[1], _state.thickness, _state.linecolour[0], _state.linecolour[1], _state.linecolour[2])
            _state.previousLinePlacement = mapPosition
    elif icon == ICON_DELETE: #deleteIcon
        if _state.mouseButton == BUTTON_LEFT:
            if _state.previousLinePlacement != None:
                clearRectangles()
                _state.nextLinePlacement = mapPosition #this is bottomRight of the square that we want to delete.
                drawRectangle(_state.previousLinePlacement[0], _state.previousLinePlacement[1],
                                      _state.nextLinePlacement[0], _state.nextLinePlacement[1], 0.8, 0.8, 1.0)
            else:
                clearRectangles()
                _state.previousLinePlacement = mapPosition #We only do this so that we have a topLeft

def mousePress(screenPosition, mapPosition, button):
    return
    #stuff below unused
    import rgeEvent

    icon = _state.menu.selectedIcon
    if icon == ICON_MOVE:
        return
    if icon == ICON_SELECT:
        if button == BUTTON_LEFT + BUTTON_CONTROL:
            if _state.pogPlacement:
                infograb = QtGui.QPixmap(_state.pogPath)
                pog = rgePog.Pog(
                    mapPosition,
                    (infograb.width(), infograb.height()),
                    (infograb.width(), infograb.height()),
                    200,
                    _state.pogPath,
                    0,
                    0,
                    {},
                    infograb.hasAlpha())
                createPog(pog)
                return
            pog = _state.session.findTopPog(mapPosition)
            if not pog:
                return
            if pog in _state.pogSelection:
                removePogSelection(pog)
            else:
                addPogSelection(pog)
            rgeEvent.pogSelectionChangedEvent()
        elif button == BUTTON_LEFT:
            if _state.pogPlacement:
                _state.pogPlacement = False
                infograb = QtGui.QPixmap(_state.pogPath)
                pog = rgePog.Pog(
                    mapPosition,
                    (infograb.width(), infograb.height()),
                    (infograb.width(), infograb.height()),
                    200,
                    _state.pogPath,
                    0,
                    0,
                    {},
                    infograb.hasAlpha())
                createPog(pog)
                return
            pog = _state.session.findTopPog(mapPosition)
            if not pog:
                clearPogSelection()
                return
            if pog not in _state.pogSelection:
                setPogSelection(pog)
            rgeEvent.pogSelectionChangedEvent()
        elif button == BUTTON_RIGHT:
            pog = _state.session.findTopPog(mapPosition)
            if pog is not None:
                _state.mouseButton = None
                if pog.hidden: hidebutton = "Show"
                else: hidebutton = "Hide"
                if pog._locked: lockbutton = "Unlock"
                else: lockbutton = "Lock"
                selected = showPopupMenuAt(
                    (screenPosition[0], screenPosition[1]),
                    [translate('views', 'Center on pog'),
                        translate('views', 'Set name'),
                        translate('views', '[UNUSED]'),
                        translate('views', 'Set layer'),
                        translate('views', 'Add/edit property'),
                        translate('views', 'Resize'),
                        translate('views', hidebutton),
                        translate('views', lockbutton),
                        translate('views', 'Delete')])
                processPogRightclick(selected, list(set([pog] + list(_state.pogSelection))))
            else:
                pass
    elif icon == ICON_DRAW:
        if button == BUTTON_LEFT:
            _state.previousLinePlacement = mapPosition
    elif icon == ICON_DELETE:
        if button == BUTTON_LEFT:
            _state.previousLinePlacement = mapPosition



def mouseRelease(screenPosition, mapPosition, button):
    _state.mouseButton = None
    return
    #stuff below unused
    icon = _state.menu.selectedIcon
    if(icon == ICON_DELETE):
        if(_state.previousLinePlacement != None and _state.nextLinePlacement != None):

            clearRectangles()

            x = _state.previousLinePlacement[0]
            y = _state.previousLinePlacement[1]
            w = _state.nextLinePlacement[0]
            h = _state.nextLinePlacement[1]
            if(x > w):
                x, w = w, x
            if(y > h):
                y, h = h, y

            w -= x
            h -= y
            #print '(x, y, w, h) (' + str(x) + ', ' + str(y) + ', ' + str(w) + ', ' + str(h) + ')'

            deleteLine(x, y, w, h)

            _state.nextLinePlacement = mapPosition

def mouseMoveResponse(x, y):
    #print 'move', x, y

    screenPosition = (x, y)
    mapPosition = getMapPosition(screenPosition)
    displacement = map(lambda p,m,d: p/d - m/d, screenPosition, _state.mousePosition,  (getZoom(), getZoom()))

    #print mapPosition
    #print cameraPosition()

    mouseMove(screenPosition, mapPosition, displacement)

    _state.mousePosition = screenPosition

def mousePressResponse(x, y, t):
    #print 'press', x, y, t

    screenPosition = (x, y)
    mapPosition = getMapPosition(screenPosition)

    _state.mousePosition = screenPosition
    _state.mouseButton = t

    mousePress(screenPosition, mapPosition, t)

def mouseReleaseResponse(x, y, t):
    #print 'release', x, y, t

    screenPosition = (x, y)
    mapPosition = getMapPosition(screenPosition)

    _state.mousePosition = screenPosition
    _state.mouseButton = t

    mouseRelease(screenPosition, mapPosition, t)

